/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.orogeny.actions.compilation;

import com.softwarecraftsmen.orogeny.filing.AbsoluteDirectory;
import com.softwarecraftsmen.orogeny.filing.AbsoluteFile;
import com.softwarecraftsmen.orogeny.filing.AbsolutePaths;
import org.jetbrains.annotations.NotNull;

import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static java.nio.charset.Charset.forName;
import static java.util.Arrays.asList;
import static java.util.Locale.UK;
import static javax.tools.StandardLocation.*;

public class ConvenientStandardJavaFileManager extends ForwardingJavaFileManager<StandardJavaFileManager>
{
	public ConvenientStandardJavaFileManager(final @NotNull JavaCompiler compiler, final @NotNull DiagnosticListener<JavaFileObject> compilerErrors, final @NotNull AbsoluteDirectory outputDirectory, final @NotNull AbsolutePaths classPath, final @NotNull AbsoluteDirectory generatedSourceOutputDirectory)
	{
		super(compiler.getStandardFileManager(compilerErrors, UK, forName("UTF-8")));
		addLocation(CLASS_OUTPUT, toFiles(outputDirectory.toFile()));
		addLocation(CLASS_PATH, toFiles(classPath.toFiles()));
		addLocation(SOURCE_OUTPUT, toFiles(generatedSourceOutputDirectory.toFile()));
	}

	public Iterable<? extends JavaFileObject> javaSourceFiles(final @NotNull Set<AbsoluteFile> sourceFiles)
	{
		return fileManager.getJavaFileObjects(getJavaFiles(sourceFiles));
	}

	private void addLocation(final StandardLocation location, final List<File> files)
	{
		try
		{
			fileManager.setLocation(location, files);
		}
		catch (IOException e)
		{
			throw new IllegalStateException(e);
		}
	}

	@SafeVarargs
	private static <T> List<T> toFiles(final @NotNull T... ts)
	{
		return asList(ts);
	}

	private static <T> List<T> toFiles(final @NotNull Set<T> ts)
	{
		return new ArrayList<>(ts);
	}

	private File[] getJavaFiles(final Set<AbsoluteFile> sourceFiles)
	{
		final File[] files = new File[sourceFiles.size()];
		int index = 0;
		for (AbsoluteFile sourceFile : sourceFiles)
		{
			files[index] = sourceFile.toFile();
			index++;
		}
		return files;
	}
}
